/*
 * CRelayChannel.cpp
 *
 *  Created on: 2016年4月30日
 *      Author: terry
 */

#include "CRelayChannel.h"
//#include "RtpPort.h"
#include "TStringUtil.h"
#include "MediaType.h"
#include "CLog.h"
#include "MediaCodecName.h"


namespace av
{

void LocalRtpSinkCallback(HANDLE handle, uint8_t* data, int size, int64_t pts, int flags, void* context)
{
	CRelayChannel* obj = (CRelayChannel*)context;
	obj->rtpSinkCallback(handle, data, size, pts, flags);
}

void AudioRtpSinkCallback(HANDLE handle, uint8_t* data, int size, int64_t pts, int flags, void* context)
{
	CRelayChannel* obj = (CRelayChannel*)context;
	obj->audioRtpSinkCallback(handle, data, size, pts, flags);
}

CRelayChannel::CRelayChannel():
		m_protocol(kProtocolUdp),
		m_rtsp(),
		m_videoRtp(),
		m_audioRtp(),
		m_videoPort(),
		m_audioPort(),
		m_format(),
        m_videoPktCount(),
        m_audioPktCount()
{

}

CRelayChannel::~CRelayChannel()
{
	close();
}

int CRelayChannel::open(int protocol, const std::string& name, const MFormat& fmt)
{
	if (name.empty())
	{
		return EINVAL;
	}

	m_protocol = protocol;
	m_name = name;

	int rc = caster_chl_open(&m_rtsp, name.c_str(), &fmt);
	if (rc != 0)
	{
		return rc;
	}

	int port = 0;
	rc = rtpsink_open(&m_videoRtp, m_protocol, port);
	rtpsink_set_callback(m_videoRtp, LocalRtpSinkCallback, this);

	m_videoPort = rtpsink_get_port(m_videoRtp);

	rtpsink_open(&m_audioRtp, m_protocol, port);
	rtpsink_set_callback(m_audioRtp, AudioRtpSinkCallback, this);

	m_audioPort = rtpsink_get_port(m_audioRtp);

	return rc;
}

std::string CRelayChannel::getName()
{
	return m_name;
}

void CRelayChannel::close()
{
	if (m_rtsp != NULL)
	{
		caster_chl_close(m_rtsp);
		m_rtsp = NULL;
	}

	if (m_videoRtp != NULL)
	{
		rtpsink_close(m_videoRtp);
		m_videoRtp = NULL;
	}

	if (m_audioRtp != NULL)
	{
		rtpsink_close(m_audioRtp);
		m_audioRtp = NULL;
	}
}

bool CRelayChannel::isOpen()
{
	return (m_rtsp != NULL);
}

int CRelayChannel::setSource(const std::string& videoUrl, const std::string& audioUrl)
{
	int rc = setVideoSource(videoUrl);
	setAudioSource(audioUrl);

	if (rc == 0)
	{
		rc = caster_chl_set_format(m_rtsp, &m_format);
	}

	return rc;
}


bool CRelayChannel::getFormat(MFormat* fmt)
{
	if (m_videoRtpFormat.empty())
	{
		return false;
	}

	fmt->codec = MediaCodecName::codecFromName(m_videoRtpFormat.m_codec);
	//fmt->width = m_videoRtpFormat.m_fmtp

	return true;
}

HANDLE CRelayChannel::getRtspCaster()
{
	return m_rtsp;
}

std::string CRelayChannel::getTransport(std::string& audioUrl)
{
	std::string scheme = RtpMediaFormat::RTP_OVER_UDP;
	if (m_protocol == kProtocolTcp)
	{
		scheme = RtpMediaFormat::RTP_OVER_TCP;
	}

	audioUrl = comn::StringUtil::format("%s://%s:%d", scheme.c_str(), "0.0.0.0",  m_audioPort);

	return comn::StringUtil::format("%s://%s:%d", scheme.c_str(), "0.0.0.0", m_videoPort);
}

void CRelayChannel::rtpSinkCallback(HANDLE handle, uint8_t* data, int size, int64_t pts, int flags)
{
    if (m_videoPktCount <= 1)
    {
        CLog::debug("video rtp. size:%d, pts:%d\n", size, (int)pts / 90);
    }
    m_videoPktCount++;

    MPacket pkt;
    memset(&pkt, 0, sizeof(pkt));
    pkt.data = data;
    pkt.size = size;
    pkt.pts = pts;
    pkt.flags = flags;
    caster_chl_write_video(m_rtsp, &pkt);
}

void CRelayChannel::audioRtpSinkCallback(HANDLE handle, uint8_t* data, int size, int64_t pts, int flags)
{
    if (m_audioPktCount <= 1)
    {
        CLog::debug("audio rtp. size:%d, pts:%d\n", size, (int)pts / 8);
    }
    m_audioPktCount++;

    MPacket pkt;
    memset(&pkt, 0, sizeof(pkt));
    pkt.data = data;
    pkt.size = size;
    pkt.pts = pts;
    pkt.flags = flags;
    caster_chl_write_audio(m_rtsp, &pkt);
}

int CRelayChannel::setVideoSource(const std::string& videoUrl)
{
	if (!m_videoRtpFormat.parse(videoUrl))
	{
		return EBADF;
	}

	m_format.codec = MediaCodecName::codecFromName(m_videoRtpFormat.m_codec);
	m_format.clockRate = m_videoRtpFormat.m_clockRate;

	int rc = rtpsink_set_format(m_videoRtp, m_format.codec, m_format.clockRate);

	return rc;
}

int CRelayChannel::setAudioSource(const std::string& audioUrl)
{
	if (!m_audioRtpFormat.parse(audioUrl))
	{
		return EBADF;
	}

	m_format.audioCodec = MediaCodecName::codecFromName(m_audioRtpFormat.m_codec);
	m_format.audioRate = m_audioRtpFormat.m_clockRate;
	m_format.sampleRate = m_audioRtpFormat.m_clockRate;
	m_format.channels = m_audioRtpFormat.m_channels;

	int rc = rtpsink_set_format(m_audioRtp, m_format.audioCodec, m_format.sampleRate);

	return rc;
}



} /* namespace av */
